/**
  ETFAna project, Anyang Normal University && IMP-CAS
  \class ETFOnlineTask
  \brief to create histograms upon user demands and pass them to GUI system
  also responsible for initiate the GUI system
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2023-07-01
  \date 2024-03-01 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2023-07-01   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021-2024 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#include <TTree.h>
#include <TH2F.h>
#include <TH1F.h>
#include "ETFOnlineTask.h"
#include "ETFParaManager.h"
#include "ETFHistManager.h"
#include "ETFGOnline.h"
#include "ETFRun.h"
#include "ETFYaml.h"
#include "ETFMsg.h"

#define er ETFMsg::Error

ETFOnlineTask::ETFOnlineTask(const char *name) : ETFTask(name){}

ETFOnlineTask::~ETFOnlineTask(){
  for(auto p : fHCMDs) delete p;
  for(auto p : fHists) delete p;
} // end dtor

void ETFOnlineTask::Init(){
  ETFTask::Init(); // then the histos can be created here
  fConfig = fpm->GetOnlinePara();
  fGOnline = fRun->GetGOnline(); // first we have fGOnline
  fGOnline->SetOnlineTask(this);
  AddHistos(); // add histos to the online GUI
} // end member function Init

// collect hists defined in other tasks
void ETFOnlineTask::AddHistos(){
  TH1 *h = nullptr;
  // allowed button_group defined in ETFGOnline:
  // {"beam", "daq", "tof", "pos", "pid", "dcMul", "dcDis", "f1", "trk"}
  const std::pair <const char *, const char *> p[] = { // {"hname", "button_group"}
    // {"hSecLenPXI", "daq"}, {"hCh", "daq"}, {"hTimeToTrigC0", "daq"},
  };
  for(const auto &t : p) if((h = fhm->GetHist(t.first)))
    fHists.push_back(new hcmd_t{.hist = h, .varexp = "", .cut = "", .opt = "colz",
      .group = t.second, .ev0 = 0});

  LoadConfigFile();
} // end member function AddHistos

// fill the cmd-hist
void ETFOnlineTask::Update(){
  for(auto c : fHCMDs){
    fTree->Project(c->hname.data(), c->varexp.data(), c->cut.data(), c->opt.data(),
      10000, c->ev0); // TTree::kMaxEntries
    c->ev0 = fTree->GetEntriesFast(); // update the entry start
  } // end for
} // end member function Update

void ETFOnlineTask::AddHist(const string &grp, const string &varexp, const string &hname,
  int nbinsx, double xlow, double xup, const string &cut, const string &opt){
  TH1 *h = new TH1F(hname.data(), varexp.data(), nbinsx, xlow, xup);
  hcmd_t *c = new hcmd_t{.hist = h, .varexp = varexp, .cut = cut, .opt = opt,
    .group = grp, .ev0 = 0};
  c->hname = "+" + hname; // accumulative filling
  fHCMDs.push_back(c);
  fGOnline->AddHist(c);
} // end member function AddHist

void ETFOnlineTask::AddHist(const string &grp, const string &varexp, const string &hname,
  int nbinsx, double xlow, double xup, int nbinsy, double ylow, double yup,
  const string &cut, const string &opt){
  TH1 *h = new TH2F(hname.data(), varexp.data(), nbinsx, xlow, xup, nbinsy, ylow, yup);
  hcmd_t *c = new hcmd_t{.hist = h, .varexp = varexp, .cut = cut, .opt = opt,
    .group = grp, .ev0 = 0};
  c->hname = "+" + hname; // accumulative filling
  fHCMDs.push_back(c);
  fGOnline->AddHist(c);
} // end member function AddHist

// load the yaml config file and update hist list
void ETFOnlineTask::LoadConfigFile(){
  fRun->Lock();
  fpm->ReloadOnlineConfig(); // read online.yaml again to include the changes
  const auto &c = *fpm->GetOnlinePara();
  // update hists //
  for(const auto &p : fGOnline->HistGroup()) if(c[p.first]){
    for(const auto &h : c[p.first]){
      const size_t size = h.size();
      if(size < 5) er("ETFOnlineTask", "LoadConfigFile: illegal yaml file format");
      string varexp = h[0].as<string>(), hname = h[1].as<string>(), cut = "", opt = "colz";
      if(hasHist(hname)) continue; // already exists
      const int nbinsx = h[2].as<int>();
      const double xlow = h[3].as<double>(), xup = h[4].as<double>();
      if(size <= 7){ // 1D histogram
        if(h[5]) cut = h[5].as<string>();
        if(h[6]) opt = h[6].as<string>();
        AddHist(p.first, varexp, hname, nbinsx, xlow, xup, cut, opt);
      } // end if
      else{ // 2D histograms
        const int nbinsy = h[5].as<int>();
        const double ylow = h[6].as<double>(), yup = h[7].as<double>();
        if(h[8]) cut = h[8].as<string>();
        if(h[9]) opt = h[9].as<string>();
        AddHist(p.first, varexp, hname, nbinsx, xlow, xup,
          nbinsy, ylow, yup, cut, opt);
      } // end else
    } // end for over items
  } // end for over tabs
  fRun->Unlock();
} // end member function LoadConfigFile

bool ETFOnlineTask::hasHist(const string &hname){
  for(auto c : fHists) if(c->hname == ("+" + hname)) return true;
  for(auto c : fHCMDs) if(c->hname == ("+" + hname)) return true;
  return false;
} // end member function hasHist
